package com.hsmpay.yl8583.utils;

import org.apache.log4j.Logger;
import com.hsmpay.utils.WriteFile;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

public class Package64{
//	static WriteFile wf = new WriteFile("anxinyb");
	private static Logger log = Logger.getLogger(Package64.class);
	
	private final static byte[][] BITMAP_INIT=
	{
		{(byte) 0x00,0x40,0x20,0x10,0x08,0x04,0x02,0x01},//1
		{(byte) 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01},//2
		{(byte) 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01},//3
		{(byte) 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01},//4
		{(byte) 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01},//5
		{(byte) 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01},//6
		{(byte) 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01},//7
		{(byte) 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01} //8
	};
	//创建BitMap
	public static byte[] CreateBitMap(Set<Integer> sets){		
		byte []bitMap=new byte[8];
		for(Integer one:sets){
			int i=(one.intValue()-1)/8;
			int j=(one.intValue()-1)%8;
			//log.debug("one.intValue=["+one.intValue()+"]");
			//log.debug("one.intValue()/8=["+i+"]");
			//log.debug("one.intValue()%8=["+j+"]");
			//log.debug("bitMap[i]%8=["+Integer.toBinaryString(bitMap[i]&0xFF)+"]");
			bitMap[i]=(byte) (BITMAP_INIT[i][j]|bitMap[i]);
		    //log.debug("i=["+i+"]"+ String.format("%1$08d",Integer.parseInt(Integer.toBinaryString(bitMap[i]&0xFF))));
		}
		return bitMap;
	}
	//获取BitMap
	public static Set<Integer> BitMap2Set(byte[] bitmap){
		Set<Integer> sets=new TreeSet<Integer>();
		StringBuilder string_bitmap=new StringBuilder();
		for(byte b:bitmap){
			log.debug(String.format("%1$08d",Integer.parseInt(Integer.toBinaryString(b&0xFF))));
			string_bitmap.append(String.format("%1$08d",Integer.parseInt(Integer.toBinaryString(b&0xFF))));
		}
		log.debug("string_bitmap=["+string_bitmap+"]");
		for(int i=1;i<string_bitmap.toString().toCharArray().length;i++){
			if(string_bitmap.toString().toCharArray()[i]=='1')
			{
				sets.add(i+1);
			}
		}
		return sets;
	}
	//组包
	public byte[] package64() throws Exception{
		ByteArrayOutputStream writer=null;
		try{
			writer=new ByteArrayOutputStream();
			writer.write(tpdu);
			writer.write(header);
			writer.write(messagetype);
			writer.write(bitmap);
			for(Integer one:data.keySet()){
				writer.write(data.get(one).toByte());
			}			
			return writer.toByteArray();
		}catch(Exception ex){
			throw new ExceptionInInitializerError(ex);
		}finally{
			try{
				writer.close();
			}catch(Exception ex){
				ex.printStackTrace();
			}
		}
	}
	//解包
	public static String UnPackage(byte[] data,String retBit,WriteFile wf){
		ByteArrayInputStream reader=null;
		Package64 pac=null;
		Field field=null;
		String retMsg="";
		String retBitValue[] =null;
		String retBitArr[]=retBit.split("\\,");
		retBitValue=new String[retBitArr.length];
    	try{
    		reader=new ByteArrayInputStream(data);
    		pac=new Package64();
    		wf.log("-------------------响应包域值信息-------------------","调试");
    		reader.read(pac.tpdu);
    		wf.log("[tpdu]="+PackageUtil.byte2hex(pac.tpdu),"调试");
    		reader.read(pac.header);
    		wf.log("[header]="+PackageUtil.byte2hex(pac.header),"调试");
    		reader.read(pac.messagetype);
    		wf.log("[messagetype]="+PackageUtil.byte2hex(pac.messagetype),"调试");
    		reader.read(pac.bitmap);
    		wf.log("[bitmap]="+PackageUtil.byte2hex(pac.bitmap),"调试");
    		Set<Integer> sets=BitMap2Set(pac.bitmap);
    		for(Integer one:sets){
    			field=(Field)SpringUtil.getApplicationContext().getBean("bit"+one);
    			field.valueof(reader);
    			String value="";
    			switch(field.getType()){
    			case BCD:
    				value=PackageUtil.byte2hex(field.getValue());
    				break;
    			case ASCII:
    				//value=new String(field.getValue(),"US-ASCII");
    				if(one==63)
    				{
    					value=PackageUtil.byte2hex(field.getValue());
    					//value=PackageUtil.byte2hex(PackageUtil.ASCII2BCD(field.getValue()));
    				}else{
	    				byte t[]=field.getValue();
	    				for(int i=0;i<t.length;i++)
	    				{
	    					if(t[i]==0)
	    						t[i]=0x20;
	    				}
	    				value=new String(t,"GBK");
    				}
    				break;
    			case BINARY:
    				value=PackageUtil.byte2hex(field.getValue());
    				break;
    			}
    			wf.log("bit"+one.toString()+":"+value,"调试");
    			if(one==60)
    			{
    				if(value.length() > 8)
    					value=value.substring(2, 8);
    			}
    			/*if(one==62)//&&  "0910".equals(PackageUtil.byte2hex(pac.messagetype))  兼容辽宁银联去掉 
    			{
    				//单DES
    				//value=value.substring(0, 16)+"_"+value.substring(24,40);
    				//3DES
    				log.debug("value = "+value);
    				log.debug("messagetype = "+PackageUtil.byte2hex(pac.messagetype));
    				log.debug("messagetype = "+pac.messagetype);
    				log.debug("messagetype = "+PackageUtil.getCnASCII(PackageUtil.byte2hex(pac.messagetype)));
    				if(value.length() == 288 && "0810".equals(PackageUtil.byte2hex(pac.messagetype))){//EBC 接口需要这个密钥
    					value = PackageUtil.toStringHex(value);//转为BCD 16进制
    					value=value.substring(0, 32)+"_"+value.substring(48,80)+"_"+value.substring(96,128);
    				}else if(value.length() > 32){
    					value=value.substring(0, 32)+"_"+value.substring(40,72);
    				} 
    			}*/
    			//54域可用佘额
    			if(one==54)
    			{
    				if(value.length() <= 1) continue;
					if(value.length() > 20){
						value = value.substring(0,20);
					}
    				
    				String ACCOUNT_TYPE="";		//帐户类型(10:储蓄帐户,30:信用卡帐户)
    				//String AMOUNT_TYPE="";		//数量类型(02:可用佘额)
    				String CURRENCY_CODE="";	//货币代码(156:人民币,其它:美元)
    				String AMOUNT_SIGN="";		//余额符号(C:正,其它:负)
    				Double AMOUNT=0.00;			//佘额(12位表示,分为单位)
    				String AmountStr="";
    				ACCOUNT_TYPE=value.substring(0, 2);
    				//AMOUNT_TYPE=value.substring(2, 4);
    				CURRENCY_CODE=value.substring(4,7);
    				AMOUNT_SIGN=value.substring(7, 8);
    				AMOUNT=Double.parseDouble(value.substring(8))/100;
    				/*
    				log.debug("ACCOUNT_TYPE:"+ACCOUNT_TYPE);
    				log.debug("AMOUNT_TYPE:"+AMOUNT_TYPE);
    				log.debug("CURRENCY_CODE:"+CURRENCY_CODE);
    				log.debug("AMOUNT_SIGN:"+AMOUNT_SIGN);
    				log.debug("AMOUNT:"+value.substring(8));
    				*/
    				if(ACCOUNT_TYPE.equals("10"))
    				{
    					AmountStr+="储蓄帐户 ";
    				}else if(ACCOUNT_TYPE.equals("30"))
    				{
    					AmountStr+="信用卡帐户 ";
    				}
    				if(CURRENCY_CODE.equals("156"))
    				{
    					AmountStr+="￥";
    				}else{
    					AmountStr+="$";
    				}
    				if(!AMOUNT_SIGN.equals("C"))
    				{
    					AmountStr+="-";
    				}
    				AmountStr+=AMOUNT;
    				value=AmountStr;
    			}
    			for(int i=0;i<retBitArr.length;i++)
    			{
    				if(one==Integer.parseInt(retBitArr[i]))
    				{
    					retBitValue[i]=value;
    					break;
    				}
    			}
    		}
    		wf.log("----------------------------------------------------","调试");
    		for(int j=0;j<retBitValue.length;j++)
    		{
    			String val=retBitValue[j];
    			if(val==null)
    				val=" ";
    			retMsg+="_"+val;
    		}
    	}catch(Exception ex){
    		log.debug("UnPackage failed." + ex);
            throw new ExceptionInInitializerError(ex);
    	}finally{
    		try{
    			reader.close();
    		}catch(Exception ex){
    			ex.printStackTrace();
    		}
    	}
    	return retMsg;
	}
	public static String newUnPackage(byte[] data,String retBit,WriteFile wf){
		ByteArrayInputStream reader=null;
		Package64 pac=null;
		Field field=null;
		String retMsg="";
		String retBitValue[] =null;
		String retBitArr[]=retBit.split(",");
		retBitValue=new String[retBitArr.length];
		try{
			reader=new ByteArrayInputStream(data);
			pac=new Package64();
			wf.log("-------------------响应包域值信息-------------------","调试");
			reader.read(pac.tpdu);
			wf.log("[tpdu]="+PackageUtil.byte2hex(pac.tpdu),"调试");
			reader.read(pac.header);
			wf.log("[header]="+PackageUtil.byte2hex(pac.header),"调试");
			reader.read(pac.messagetype);
			wf.log("[messagetype]="+PackageUtil.byte2hex(pac.messagetype),"调试");
			reader.read(pac.bitmap);
			wf.log("[bitmap]="+PackageUtil.byte2hex(pac.bitmap),"调试");
			Set<Integer> sets=BitMap2Set(pac.bitmap);
			for(Integer one:sets){
				field=(Field)PospSpringUtil.getApplicationContext().getBean("bit"+one);
				field.valueof(reader);
				String value="";
				switch(field.getType()){
					case BCD:
						value=PackageUtil.byte2hex(field.getValue());
						break;
					case ASCII:
						//value=new String(field.getValue(),"US-ASCII");
						if(one==63)
						{
							value=PackageUtil.byte2hex(field.getValue());
							//value=PackageUtil.byte2hex(PackageUtil.ASCII2BCD(field.getValue()));
						}else{
							byte t[]=field.getValue();
							for(int i=0;i<t.length;i++)
							{
								if(t[i]==0)
									t[i]=0x20;
							}
							value=new String(t,"GBK");
						}
						break;
					case BINARY:
						value=PackageUtil.byte2hex(field.getValue());
						break;
				}
				wf.log("bit"+one.toString()+":"+value,"调试");
				if(one==60)
				{
					if(value.length() > 8)
						value=value.substring(2, 8);
				}
    			/*if(one==62)//&&  "0910".equals(PackageUtil.byte2hex(pac.messagetype))  兼容辽宁银联去掉
    			{
    				//单DES
    				//value=value.substring(0, 16)+"_"+value.substring(24,40);
    				//3DES
    				log.debug("value = "+value);
    				log.debug("messagetype = "+PackageUtil.byte2hex(pac.messagetype));
    				log.debug("messagetype = "+pac.messagetype);
    				log.debug("messagetype = "+PackageUtil.getCnASCII(PackageUtil.byte2hex(pac.messagetype)));
    				if(value.length() == 288 && "0810".equals(PackageUtil.byte2hex(pac.messagetype))){//EBC 接口需要这个密钥
    					value = PackageUtil.toStringHex(value);//转为BCD 16进制
    					value=value.substring(0, 32)+"_"+value.substring(48,80)+"_"+value.substring(96,128);
    				}else if(value.length() > 32){
    					value=value.substring(0, 32)+"_"+value.substring(40,72);
    				}
    			}*/
				//54域可用佘额
				if(one==54)
				{
					if(value.length() <= 1) continue;

					String ACCOUNT_TYPE="";		//帐户类型(10:储蓄帐户,30:信用卡帐户)
					//String AMOUNT_TYPE="";		//数量类型(02:可用佘额)
					String CURRENCY_CODE="";	//货币代码(156:人民币,其它:美元)
					String AMOUNT_SIGN="";		//余额符号(C:正,其它:负)
					Double AMOUNT=0.00;			//佘额(12位表示,分为单位)
					String AmountStr="";
					ACCOUNT_TYPE=value.substring(0, 2);
					//AMOUNT_TYPE=value.substring(2, 4);
					CURRENCY_CODE=value.substring(4,7);
					AMOUNT_SIGN=value.substring(7, 8);
					AMOUNT=Double.parseDouble(value.substring(8))/100;
    				/*
    				log.debug("ACCOUNT_TYPE:"+ACCOUNT_TYPE);
    				log.debug("AMOUNT_TYPE:"+AMOUNT_TYPE);
    				log.debug("CURRENCY_CODE:"+CURRENCY_CODE);
    				log.debug("AMOUNT_SIGN:"+AMOUNT_SIGN);
    				log.debug("AMOUNT:"+value.substring(8));
    				*/
					if(ACCOUNT_TYPE.equals("10"))
					{
						AmountStr+="储蓄帐户 ";
					}else if(ACCOUNT_TYPE.equals("30"))
					{
						AmountStr+="信用卡帐户 ";
					}
					if(CURRENCY_CODE.equals("156"))
					{
						AmountStr+="￥";
					}else{
						AmountStr+="$";
					}
					if(!AMOUNT_SIGN.equals("C"))
					{
						AmountStr+="-";
					}
					AmountStr+=AMOUNT;
					value=AmountStr;
				}
				for(int i=0;i<retBitArr.length;i++)
				{
					if(one==Integer.parseInt(retBitArr[i]))
					{
						retBitValue[i]=value;
						break;
					}
				}
			}
			wf.log("----------------------------------------------------","调试");
			for(int j=0;j<retBitValue.length;j++)
			{
				String val=retBitValue[j];
				if(val==null)
					val=" ";
				retMsg+="_"+val;
			}
		}catch(Exception ex){
			log.debug("UnPackage failed." + ex);
			throw new ExceptionInInitializerError(ex);
		}finally{
			try{
				reader.close();
			}catch(Exception ex){
				ex.printStackTrace();
			}
		}
		return retMsg;
	}
    protected byte[] tpdu=new byte[5];
    protected byte[] header=new byte[6];
    protected byte[] bitmap =new byte[8];
    protected byte[] messagetype=new byte[2];
    protected TreeMap<Integer,Field> data =new TreeMap<Integer,Field>();

	public byte[] getTpdu() {
		return tpdu;
	}
	public void setTpdu(byte[] tpdu) {
		this.tpdu = tpdu;
	}
	public byte[] getHeader() {
		return header;
	}
	public void setHeader(byte[] header) {
		this.header = header;
	}
	public byte[] getBitmap() {
		return bitmap;
	}
	public void setBitmap(byte[] bitmap) {
		this.bitmap = bitmap;
	}
	public byte[] getMessagetype() {
		return messagetype;
	}
	public void setMessagetype(byte[] messagetype) {
		this.messagetype = messagetype;
	}
	public TreeMap<Integer, Field> getData() {
		return data;
	}
	public void setData(TreeMap<Integer, Field> data) {
		this.data = data;
	}

	
	public static void main(String args[]){
		String LoginMsg = "0_00_000001_BFE9B03C79CF187BA02E8415378614C1C22047CE875649A4681F046E00000000000000002D436B76";
		if(LoginMsg.length()>50){
			String startMsg = LoginMsg.substring(0, LoginMsg.lastIndexOf("_"));
			String bit62 = LoginMsg.substring(LoginMsg.lastIndexOf("_")+1);
			bit62 = bit62.substring(0, 32)+"_"+bit62.substring(40,56)+bit62.substring(40,56);
			LoginMsg = startMsg+"_"+bit62;
		}
		System.out.println(LoginMsg);
	}
}
